package com.ytt.bean;

import com.ytt.bean.dobean.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 切面。
 *  aspect. 面
 */
@Aspect
public class MyAspect {

    /**
     * 前置通知
     */
    @Before("execution(* com.ytt.dao.UserDao.addUserAAA(..))")
    public void before(JoinPoint point){
        Object[] args=point.getArgs(); // 参数值
        Signature signature= point.getSignature(); // 获得方法签名
        Object o= point.getTarget(); // 返回被织入增强处理的目标对象
        Object oo=point.getThis(); //返回AOP框架为目标对象生成的代理对象

        try {
            Method method= o.getClass().getMethod(point.getSignature().getName(),User.class);
            Annotation[][] annotations=method.getParameterAnnotations();
            NotNull notNull= (NotNull)annotations[0][0];
            if(notNull.canNull()){

            }else {
                if(null==args[0]){
                    throw new MyException("这里不能是null偶");
                }
            }
            System.out.println( notNull.canNull());
            System.out.println("aa");

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        System.out.println("@Before：目标方法为：" +
                point.getSignature().getDeclaringTypeName() +
                "____" + point.getSignature().getName());
        System.out.println("前置通知....");
    }

    /**
     * 后置通知
     * returnVal,切点方法执行后的返回值
     */
    @AfterReturning(value="execution(* com.ytt.dao.UserDao.addUserAAA(..))",returning = "returnVal")
    public void AfterReturning(Object returnVal){
        System.out.println("后置通知...."+returnVal);
    }


    /**
     * 环绕通知
     * @param joinPoint 可用于执行切点的类
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.ytt.dao.UserDao.addUserAAA(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知前....");


        Object[] args=joinPoint.getArgs();
        //args[0]=null; // 可以改变参数值
        Object obj= (Object) joinPoint.proceed(args); //调用目标方法。


        System.out.println("环绕通知后....");
        return obj;
    }

    /**
     * 抛出通知
     * @param e
     */
    @AfterThrowing(value="execution(* com.ytt.dao.UserDao.addUserAAA(..))",throwing = "e")
    public void afterThrowable(Throwable e){
        System.out.println("出现异常:msg="+e.getMessage());
    }

    /**
     * 无论什么情况下都会执行的方法
     */
    @After(value="execution(* com.ytt.dao.UserDao.addUserAAA(..))")
    public void after(){
        System.out.println("最终通知....");
    }
}